﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using NUnit.Framework;
using Smith.AMC.Configuration;
using Smith.AMC.Network;


namespace MemcachedClientTests
{
    [TestFixture]
    public class ServerPoolTest
    {
        private List<KeyValuePair<IPAddress, int>> servers = new List<KeyValuePair<IPAddress, int>>();


        [TestFixtureSetUp]
        public void PerTestSetUp()
        {
            servers.Add(new KeyValuePair<IPAddress, int>(IPAddress.Parse("127.0.0.1"), 11211));
            //servers.Add(new KeyValuePair<IPAddress, int>(IPAddress.Parse("127.0.0.1"), 11212));
        }

        [Test]
        public void ThreadingWith5timesTheThreadsOfThePoolSizeTest()
        {
            ServerNodeMonitorConfiguration config = new ServerNodeMonitorConfiguration();
            ServerPool pool = new ServerPool(servers, SocketType.Stream, ProtocolType.Tcp, 10, config);
            ManualResetEvent quit = new ManualResetEvent(false);
            List<Thread> threads = new List<Thread>();
            long aquires = 0;
            long tries = 0;
            long exceptions = 0;

            for (int i = 0; i < 50; i++)
            {
                Thread t = new Thread(obj =>
                {

                    do
                    {
                        Interlocked.Increment(ref tries);
                        IClientSocket clientSocket = null;
                        try
                        {
                            clientSocket = pool.AquireSocket(TimeSpan.FromSeconds(1), "Thread");
                            Interlocked.Increment(ref aquires);
                            pool.ReleaseSocket(clientSocket);
                        }
                        catch (Exception e)
                        {
                            Interlocked.Increment(ref exceptions);
                            Console.WriteLine(e);
                        }
                        finally
                        {
                            if (clientSocket != null)
                            {
                                pool.ReleaseSocket(clientSocket);
                            }
                        }

                    } while (!quit.WaitOne(1, false));
                })
                {
                    Name = "Thread" + i
                };
                threads.Add(t);
                t.Start();
            }

            Thread.Sleep(1000);
            quit.Set();

            threads.ForEach(t => t.Join());

            Console.WriteLine("Tries:{0}", tries);
            Console.WriteLine("Aquires:{0}", aquires);
            Console.WriteLine("Exceptions:{0}", exceptions);

            Assert.That(0, Is.EqualTo(exceptions));
            Assert.That(aquires, Is.EqualTo(tries));

        }
    }
}
